#include <stdio.h>
#include <sys/io.h>

/*
  connections:
  STROBE   --> CLK
  AUTOFEED --> CLR
  ERR <------- DATA
 */


#define REALLY_SLOW_IO

/* parallel port address */
#define port_base       0x378
#define port_status     port_base + 1
#define port_control    port_base + 2
/* data byte out */
#define port_out(byte)  outb_p(byte,port_base)
/* control register bits */
#define update_ctl      outb_p(ctrport,port_control)
#define update_dat      port_out(datport)
#define STROBE_HIGH	ctrport &= ~0x01; update_ctl  /* inverted */
#define STROBE_LOW	ctrport |= 0x01; update_ctl   /* inverted */
#define AUTOFEED_HIGH	ctrport &= ~0x02; update_ctl /* inverted */
#define AUTOFEED_LOW	ctrport |= 0x02; update_ctl  /* inverted */
#define nINIT_HIGH	  ctrport |= 0x04; update_ctl  /* non-inverted */
#define nINIT_LOW	  ctrport &= ~0x04; update_ctl /* non-inverted */
#define SELECT_HIGH	  ctrport &= ~0x08; update_ctl /* inverted */
#define SELECT_LOW	  ctrport |= 0x08; update_ctl  /* inverted */

/* needed status register bits */
#define ERR             0x08
#define bit_in          (inb_p(port_status) & ERR)

/* functions */
#define CLK_HIGH        SELECT_HIGH
#define CLK_LOW         SELECT_LOW
#define CHIP_CLR        nINIT_LOW /* ? */
#define CHIP_ENABLE     nINIT_HIGH

/* parallel port direction control */
#define PCD	        0x20
#define port_write      ctrport &= ~PCD; update_ctl
#define port_read       ctrport |= PCD; update_ctl

static unsigned char ctrport, datport=0;

static void init_port() /* Initialize parallel port */
{
  if (ioperm(port_base,3,1))
  {
    fprintf(stderr, "Error: Couldn't get the port at %x\n", port_base);
    fprintf(stderr, "Note: you MUST run this program as root.\n");
    exit(1);
  }
  ioperm(0x80,3,1);
  ctrport = inb(port_control);
  port_write;
  update_dat;
}


int main()
{
  unsigned int i;
  char b;
  init_port();	
  while (1)
  {
    printf("select:\n");
    printf("1) set CLR HIGH\n");
    printf("2) set CLR LOW\n");
    printf("3) set CLK HIGH\n");
    printf("4) set CLR LOW\n");
    printf("5) set value\n");
    printf("6) get OUT\n");
    printf("7) quit\n");
    scanf("%d",&i);    
    switch(i)
      {
      case 1:
	CHIP_ENABLE;
	break;
      case 2:
	CHIP_CLR;
	break;
      case 3:
	CLK_HIGH;
	break;
      case 4:
	CLK_LOW;
	break;
      case 5:
	scanf("%d",&b);
	CHIP_CLR;
	usleep(100);
	CHIP_ENABLE;
	while(b--) {
	  CLK_HIGH;
	  CLK_LOW;
	}
	break;
      case 6:
	b = bit_in/1;
	printf("bit = %d\n", i, b);
	break;
      case 7:
	exit(0);
	break;
      }

  }
  return 0;
}
